package com.delay.queue.delayedqueue.rabbitmq;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @desc: 延时队列 TTL+DLX
 * @author: gxing
 * @date: 2020/7/16
 */
@Configuration
public class RabbitMQConfig {

    // 延时
    public static final String DELAY_EXCHANGE_NAME = "delay.exchange";
    public static final String DELAY_QUEUE_NAME = "delay.queue";
    public static final String DELAY_MESSAGE_ROUTE_KEY = "delay.route.key";
    // 死信
    public static final String DEAD_LETTER_EXCHANGE_NAME = "dead.letter.exchange";
    public static final String DEAD_LETTER_QUEUE_NAME = "dead.letter.queue";
    public static final String DEAD_LETTER_ROUTE_KEY = "dead.letter.route.key";

    /**
     * 声明延时交换器
     *
     * @return
     */
    @Bean(name = "delayExchange")
    public DirectExchange delayExchange() {
        return new DirectExchange(DELAY_EXCHANGE_NAME);
    }

    /**
     * 声明延时队列
     *
     * @return
     */
    @Bean(name = "delayQueue")
    public Queue delayQueue() {
        Map<String, Object> args = new HashMap<>(2);
        // x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE_NAME);
        // x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTE_KEY);
        // x-message-ttl  声明队列的TTL
        args.put("x-message-ttl", 10000);
        return QueueBuilder.durable(DELAY_QUEUE_NAME).withArguments(args).build();
    }

    /**
     * 声明死信交换器
     *
     * @return
     */
    @Bean(name = "deadLetterExchange")
    public DirectExchange deadLetterExchange() {
        return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME);
    }

    /**
     * 声明死信队列
     *
     * @return
     */
    @Bean(name = "deadLetterQueue")
    public Queue deadLetterQueue() {
        return QueueBuilder.nonDurable(DEAD_LETTER_QUEUE_NAME).build();
    }

    /**
     * 延时队列绑定延时交换器
     *
     * @param delayExchange
     * @param delayExchange
     * @return
     */
    @Bean
    public Binding delayQueueBind(@Qualifier(value = "delayQueue") Queue delayQueue,
                                  @Qualifier(value = "delayExchange") DirectExchange delayExchange) {
        return BindingBuilder.bind(delayQueue).to(delayExchange).with(DELAY_MESSAGE_ROUTE_KEY);
    }

    /**
     * 死信队列绑定死信交换器
     *
     * @param deadLetterQueue
     * @param deadLetterExchange
     * @return
     */
    @Bean
    public Binding deadLetterQueueBind(@Qualifier(value = "deadLetterQueue") Queue deadLetterQueue,
                                       @Qualifier(value = "deadLetterExchange") DirectExchange deadLetterExchange) {
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with(DEAD_LETTER_ROUTE_KEY);
    }

    /*----------------RabbitMQ Plugin：rabbitmq_delayed_message_exchange Plugin------------------------*/
    public static final String X_DELAYED_EXCHANGE_NAME = "x-delayed-exchange";
    public static final String X_DELAYED_EXCHANGE_TYPE = "x-delayed-message";
    public static final String X_DELAYED_QUEUE_NAME = "x-delayed-queue";
    public static final String X_DELAYED_ROUTE_KEY = "x-delayed-route-key";


    /**
     * 声明延时队列
     *
     * @return
     */
    @Bean(name = "xDelayedQueue")
    public Queue xDelayedQueue() {
        return QueueBuilder.nonDurable(X_DELAYED_QUEUE_NAME).build();
    }

    /**
     * 声明延时交换器
     *
     * @return
     */
    @Bean
    public CustomExchange customExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(X_DELAYED_EXCHANGE_NAME, X_DELAYED_EXCHANGE_TYPE, true, false, args);
    }

    /**
     * 队列与交换器绑定
     *
     * @param queue
     * @param customExchange
     * @return
     */
    @Bean
    public Binding bindingNotify(@Qualifier("xDelayedQueue") Queue queue,
                                 @Qualifier("customExchange") CustomExchange customExchange) {
        return BindingBuilder.bind(queue).to(customExchange).with(X_DELAYED_ROUTE_KEY).noargs();
    }

}
